package com.fare.taluo.core.domain.queue;

import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import com.dayatang.domain.Entity;
import com.fare.taluo.GlobalsConst;
import com.fare.taluo.core.domain.BaseEntity;
import com.fare.taluo.util.ClassUtils;
import com.fare.taluo.vo.queue.QueueBaseVO;
import com.foreveross.threadpool.queue.WorkQueue;
/**
 * 线程队列实体基类
 * <p>所有需要实现threadpool中{@link WorkQueue}队列的领域对象都需要继承一下这个基类
 * <P>该基类已装队列常用属性，通过注解映射数据库，子类只需添加各自属性即可
 * @author creator: xiangsf
 * @author modifior: xiangsf
 * @since 2012-12-11 下午1:51:22
 * @version v1.0
 * 
 * @see com.foreveross.threadpool.queue.WorkQueue
 * @see com.foreveross.threadpool.queue.impl.AbstractWorkQueue
 * @see properties:planStartTime
 * @see properties:status
 */
@MappedSuperclass
public abstract class QueueBaseEntity<T extends Entity> extends com.fare.taluo.base.ddd.domain.baseentity.BaseEntity{
	/**
	 * 
	 */
	private static final long serialVersionUID = -8898100372673723997L;
	/**
	 * 队列ID
	 */
//	@Id
//	@GeneratedValue(strategy = GenerationType.AUTO, generator = FDC_SEQ_GEN)
//	@SequenceGenerator(name = FDC_SEQ_GEN, sequenceName = FDC_SEQUENCE)
//	protected Long id;
	/**
	 * 队列名称
	 */
	@Column(name = "NAME")	
	protected String name;
	/**
	 * 创建人ID
	 */
	@Column(name="creator")
	protected Long creator;
	/**
	 * 创建人名称
	 */
	@Column(name="CREATOR_NAME")
	protected String creatorName;
	/**
	 * 创建时间
	 */
	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable=false,name="create_time")
	protected Date createTime = new Date();
	/**
	 * 队列计划开始执行时间
	 * <p>threadpool线程队列池，通常根据这个时间与当前时间相比，将队列追加到池中，此时队列状态由等待转为已加载
	 */
	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable=false,name="plan_start_time")
	protected Date planStartTime = new Date();
	/**
	 * 任务加载时间
	 */
	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable=false,name="load_time")
	protected Date loadTime;
	/**
	 * 实际开始时间
	 */
	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable=true,name="start_time")
	protected Date startTime;
	/**
	 * 实际执行结束时间
	 */
	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable=true,name="end_time")
	protected Date endTime;
	/**
	 * 执行状态
	 * <p>根据队列所处环境不同，状态分为：等待、已加载、正在执行、执行成功、执行失败、暂停
	 * @see WorkQueue.STATUS_WAITING....
	 */
	@Column(name = "status")	
	protected int status = WorkQueue.STATUS_WAITING;
	/**
	 * 执行时长(单位毫秒)
	 */
	@Column(name = "SPENT_TIMES")	
	protected Long spentTimes = 0L;
	/**
	 * 记录的执行日志
	 * <p>一般地，当执行状态为WorkQueue.STATUS_FAIL执行失败时，一定要记录失败出错日志
	 */
	@Column(name = "REC_LOG")	
	protected String recLog;
	
	@Column(name = "FLG_DELETED")	
	protected int flgDeleted = GlobalsConst.FLG_NO;

	public Date getPlanStartTime() {
		return planStartTime;
	}

	public void setPlanStartTime(Date planStartTime) {
		this.planStartTime = planStartTime;
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public Date getEndTime() {
		return endTime;
	}

	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}

	public int getStatus() {
		return status;
	}

	public void setStatus(int status) {
		this.status = status;
	}

	public long getSpentTimes() {
		return spentTimes;
	}

	public void setSpentTimes(long spentTimes) {
		this.spentTimes = spentTimes;
	}

	public String getRecLog() {
		return recLog;
	}

	public void setRecLog(String recLog) {
		this.recLog = recLog;
	}

//	public Long getId() {
//		return id;
//	}
//
//	public void setId(Long id) {
//		this.id = id;
//	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public int getFlgDeleted() {
		return flgDeleted;
	}

	public void setFlgDeleted(int flgDeleted) {
		this.flgDeleted = flgDeleted;
	}

	public Date getLoadTime() {
		return loadTime;
	}

	public void setLoadTime(Date loadTime) {
		this.loadTime = loadTime;
	}

	public Long getCreator() {
		return creator;
	}

	public void setCreator(Long creator) {
		this.creator = creator;
	}

	public String getCreatorName() {
		return creatorName;
	}

	public void setCreatorName(String creatorName) {
		this.creatorName = creatorName;
	}

	
	protected abstract QueueBaseRepository<T> getEntityRepository();
	
	public abstract QueueBaseEntity<T> createNextTask(Long id) throws Exception;
	
	public abstract void executeTask(Long id) throws Exception;
	/**
	 * 获得计划内任务队列
	 * @param maxSize
	 * @return
	 */
	public List<T> getPlanTask(int maxSize) throws Exception{
		if(logger.isDebugEnabled()){
			logger.debug("加载任务!");
		}
		List<T> values = getEntityRepository().listPlanStartEntity(maxSize);
		for(T t : values){
			QueueBaseEntity<T> e = (QueueBaseEntity<T>)t;
			e.setStatus(WorkQueue.STATUS_LOADED);
			e.setLoadTime(new Date());
			BaseEntity.getRepository().save(e);
		}
		if(logger.isDebugEnabled()){
			logger.debug("获得的任务记录条数："+values.size());
		}
		return values;
	}
	/**
	 * 任务加载执行
	 * @return
	 * @throws Exception
	 */
	public boolean loadTask(Long id) throws Exception{
		if(logger.isDebugEnabled()){
			logger.info("执 行任务开始!");
		}
		
		QueueBaseEntity<T> entity = (QueueBaseEntity<T>)getEntityRepository().get(getGenericType(), id);
		if(entity.getStatus() == WorkQueue.STATUS_LOADED){
			entity.setStartTime(new Date());
			entity.setStatus(WorkQueue.STATUS_GOINGON);
			entity.save();
			return true;
		}
		return false;
	}
	
	/**
	 * 归档任务
	 * @param finalStatus
	 * @param recLog
	 * @throws Exception
	 */
	public void archiveTask(QueueBaseVO vo) throws Exception{
		
		QueueBaseEntity<T> entity = (QueueBaseEntity<T>)getEntityRepository().get(getGenericType(), vo.getId());
		
		entity.setEndTime(new Date());
		entity.setSpentTimes(entity.getEndTime().getTime()-entity.getStartTime().getTime());
		entity.setStatus(vo.getStatus());
		entity.setRecLog(vo.getRecLog());
		entity.save();
	}

	/**
	 * 任务的重置
	 * <p>将执行超时，或其它原因（比如宕机）造成的任务中止，恢复过来，使之可以重新执行
	 * 现在还没有建立任务重置线程队列池，不起作用
	 */
	public void resetTask() throws Exception{
	
	}
	
	protected Class<T> getGenericType(){
		Class<T> clazz = (Class<T>)ClassUtils.getGenericType(this.getClass());
		return clazz;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((createTime == null) ? 0 : createTime.hashCode());
		result = prime * result + ((creator == null) ? 0 : creator.hashCode());
		result = prime * result
				+ ((creatorName == null) ? 0 : creatorName.hashCode());
		result = prime * result + ((endTime == null) ? 0 : endTime.hashCode());
		result = prime * result + flgDeleted;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result
				+ ((loadTime == null) ? 0 : loadTime.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result
				+ ((planStartTime == null) ? 0 : planStartTime.hashCode());
		result = prime * result + ((recLog == null) ? 0 : recLog.hashCode());
		result = prime * result + (int) (spentTimes ^ (spentTimes >>> 32));
		result = prime * result
				+ ((startTime == null) ? 0 : startTime.hashCode());
		result = prime * result + status;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof QueueBaseEntity))
			return false;
		QueueBaseEntity other = (QueueBaseEntity) obj;
		if (createTime == null) {
			if (other.createTime != null)
				return false;
		} else if (!createTime.equals(other.createTime))
			return false;
		if (creator == null) {
			if (other.creator != null)
				return false;
		} else if (!creator.equals(other.creator))
			return false;
		if (creatorName == null) {
			if (other.creatorName != null)
				return false;
		} else if (!creatorName.equals(other.creatorName))
			return false;
		if (endTime == null) {
			if (other.endTime != null)
				return false;
		} else if (!endTime.equals(other.endTime))
			return false;
		if (flgDeleted != other.flgDeleted)
			return false;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (loadTime == null) {
			if (other.loadTime != null)
				return false;
		} else if (!loadTime.equals(other.loadTime))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (planStartTime == null) {
			if (other.planStartTime != null)
				return false;
		} else if (!planStartTime.equals(other.planStartTime))
			return false;
		if (recLog == null) {
			if (other.recLog != null)
				return false;
		} else if (!recLog.equals(other.recLog))
			return false;
		if (spentTimes != other.spentTimes)
			return false;
		if (startTime == null) {
			if (other.startTime != null)
				return false;
		} else if (!startTime.equals(other.startTime))
			return false;
		if (status != other.status)
			return false;
		return true;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("QueueBaseEntity [id=");
		builder.append(id);
		builder.append(", name=");
		builder.append(name);
		builder.append(", creator=");
		builder.append(creator);
		builder.append(", creatorName=");
		builder.append(creatorName);
		builder.append(", createTime=");
		builder.append(createTime);
		builder.append(", planStartTime=");
		builder.append(planStartTime);
		builder.append(", loadTime=");
		builder.append(loadTime);
		builder.append(", startTime=");
		builder.append(startTime);
		builder.append(", endTime=");
		builder.append(endTime);
		builder.append(", status=");
		builder.append(status);
		builder.append(", spentTimes=");
		builder.append(spentTimes);
		builder.append(", recLog=");
		builder.append(recLog);
		builder.append(", flgDeleted=");
		builder.append(flgDeleted);
		builder.append("]");
		return builder.toString();
	}
	
	
}
